<?php
// $Id: Renderer.php 27 2010-11-16 12:49:54Z mjohnson60@gmail.com $
//
// $Author: mjohnson60@gmail.com $
// $Date: 2010-10-28 06:05:27 -0400 (Thu, 28 Oct 2010) $
//
// $Rev: 9 $
//


/**
 * @name Content markers
 * @{
 * Markers used by theme_mark() and node_mark() to designate content.
 * @see theme_mark(), node_mark()
 */
define('MARK_READ', 0);
define('MARK_NEW', 1);
define('MARK_UPDATED', 2);

/**
 * Enter description here ...
 * 
 * @author Mark Phillip Johnson
 * @version 1.0
 * @copyright Copyright (c) 2010, markjohnson
 * @license http://www.gnu.org/licenses/gpl.html The GNU General Public License v3.0
 *
 */
class Renderer extends Object
{
	/**
	 * Enter description here ...
	 * 
	 * @var unknown_type
	 */
	private static $instance = NULL;
	
	/**
	 * Enter description here ...
	 * 
	 * @var unknown_type
	 */
	var $registry = array();
	
	/**
	 * Enter description here ...
	 * 
	 * @var unknown_type
	 */
	var $themes = array();

	/**
	 * Enter description here ...
	 * 
	 */
	public function __construct()
	{
		self::$instance = & $this;
	}

	/**
	 *
	 * @return <type>
	 */
	public static function &getInstance()
	{
		if (!isset(self::$instance))
		{
			new Renderer();
		}
		
		return self::$instance;
	}

	/**
	 * Enter description here ...
	 * 
	 */
	public static function render()
	{
		$_this = & Renderer::getInstance();
		
		$args = func_get_args();
		$model = array_shift($args);
		
		$output = '';
		
		if (empty($_this->registry))
		{
			global $theme;
			Renderer::buildRegistry($theme);
		}
		
		if (is_object($model) && ($model->isSubclassOf('View') || $model instanceof View))
		{
			$hook = $model->model();
			if (!isset($_this->registry[$hook]))
			{
				return;
			}
			
			$cache = $_this->registry[$hook];
			
			$variables = Renderer::prepareModel($hook, $cache, $args);
			
			$extension = '.tpl.php';
			
			if ($model->template() !== FALSE)
			{
				$suggestions = array();
				
				if (isset($variables['template_files']))
				{
					$suggestions = $variables['template_files'];
				}
				
				if (isset($variables['template_file']))
				{
					$suggestions[] = $variables['template_file'];
				}
				
				if (count($suggestions) > 0)
				{
					$template_file = Renderer::discoverTemplate($cache['path'], $suggestions, $extension);
				}
				
				if (empty($template_file))
				{
					$template_file = $hook . $extension;
					if (isset($cache['callback']))
					{
						$template_file = $cache['callback'][0] . '/' . $template_file;
					}
				}
				
				$output = Renderer::renderTemplate($template_file, $variables);
			}
			else if ($cache['route'] == 'method' || $cache['route'] == 'function')
			{
				$output = call_user_func_array($cache['callback'], $variables);
			}
			else
			{
				$output = $model->render($variables);
			}
		}
		else
		{
			if (!isset($_this->registry[$model]))
			{
				return;
			}
			
			$cache = $_this->registry[$model];
			
			$variables = Renderer::prepareModel($model, $cache, $args);
			
			$extension = '.tpl.php';
			
			if (isset($cache['callback']))
			{
				if ($cache['route'] == 'template' && is_array($cache['callback']))
				{
					$output = Renderer::renderTemplate($cache['callback'][0] . '/' . $cache['callback'][1] . $extension, $variables);
				}
				else if (($cache['route'] == 'method' && is_array($cache['callback'])) || ($cache['route'] == 'function' && function_exists($cache['callback'])))
				{
					$output = call_user_func_array($cache['callback'], $variables);
				}
			}
		}
		
		return $output;
	}

	/**
	 * Enter description here ...
	 * 
	 * @param string $model
	 * @param array $cache
	 * @return Ambigous <multitype:multitype: , unknown>
	 */
	public static function prepareModel($model, $cache, $args)
	{
		if (!empty($cache['includes']))
		{
			foreach ($cache['includes'] as $include_file)
			{
				include_once ($include_file);
			}
		}
		
		$variables = array('template_files' => array());
		
		if (!empty($cache['arguments']))
		{
			$count = 0;
			foreach ($cache['arguments'] as $name => $default)
			{
				$variables[$name] = isset($args[$count]) ? $args[$count] : $default;
				$count++;
			}
		}
		
		if (isset($cache['prerender']) && is_array($cache['prerender']))
		{
			$args = array(&$variables, $model);
			foreach ($cache['prerender'] as $class => $prerender_functions)
			{
				if (is_array($prerender_functions))
				{
					foreach ($prerender_functions as $prerender_function)
					{
						if (method_exists($class, $prerender_function))
						{
							call_user_func_array(array($class, $prerender_function), $args);
						}
					}
				}
				else
				{
					if (function_exists($prerender_functions))
					{
						call_user_func_array($prerender_functions, $args);
					}
				}
			}
		}
		
		return $variables;
	}

	/**
	 * Enter description here ...
	 * 
	 * @param array $paths
	 * @param array $suggestions
	 * @param string $extension
	 * @return string
	 */
	public static function discoverTemplate($paths, $suggestions, $extension = '.tpl.php')
	{
		global $theme_engine;
		
		// Remove slashes or null to prevent files from being included from
		// an unexpected location (especially on Windows servers).
		$extension = str_replace(array("/", "\\", "\0"), '', $extension);
		
		// Loop through all paths and suggestions in FIFO order.
		$suggestions = array_reverse($suggestions);
		$paths = array_reverse($paths);
		foreach ($suggestions as $suggestion)
		{
			if (!empty($suggestion))
			{
				$suggestion = str_replace(array("/", "\\", "\0"), '', $suggestion);
				foreach ($paths as $path)
				{
					if (file_exists($file = $path . '/' . $suggestion . $extension))
					{
						return $file;
					}
				}
			}
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param string $file
	 * @param array $variables
	 * @return string
	 */
	public static function renderTemplate($file, $variables = array())
	{
		extract($variables, EXTR_SKIP);
		
		ob_start();
		include ('./' . $file);
		
		return ob_get_clean();
	}

	/**
	 * callPrerender()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $variables
	 * @param unknown_type $model
	 * @param unknown_type $model_object
	 */
	public static function callPrerender(&$variables, $model, $model_object = NULL)
	{
		$args = array(&$variables, $model);
		
		foreach ($model_object->prerender as $function)
		{
			call_function($function, $args);
		}
	}

	/**
	 * callRenderFunction()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $args
	 * @param unknown_type $model
	 */
	public static function callRenderFunction(&$args, $model)
	{
	
	}

	/**
	 * buildRegistry()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $theme
	 * @param unknown_type $base_theme
	 * @param unknown_type $theme_engine
	 */
	public static function buildRegistry($theme, $base_theme = array(), $theme_engine = 'phptemplate')
	{
		$cache = array();
		foreach (Moduler::moduleImplements('render') as $module)
		{
			Renderer::_processRegistry($cache, $module, RENDER_TYPE_MODULE, Moduler::moduleForName($module), Athena::getPath('module', $module));
		}
		
		foreach ($base_theme as $base)
		{
			$base_path = dirname($base->filename);
			if ($theme_engine)
			{
				Renderer::_processRegistry($cache, $theme_engine, RENDER_TYPE_THEME_ENGINE, $base, $base_path);
			}
			
			Renderer::_processRegistry($cache, $base->name, RENDER_TYPE_BASE_THEME, $base, $base_path);
		}
		
		if ($theme_engine)
		{
			Renderer::_processRegistry($cache, $theme_engine, RENDER_TYPE_THEME_ENGINE, $theme, dirname($theme->filename));
		}
		
		Renderer::_processRegistry($cache, $theme->name, RENDER_TYPE_THEME, $theme, dirname($theme->filename));
		
		$_this = & Renderer::getInstance();
		$_this->registry = $cache;
	}

	/**
	 * _processRegistry()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $cache
	 * @param unknown_type $name
	 * @param unknown_type $type
	 * @param unknown_type $theme
	 * @param unknown_type $path
	 */
	public static function _processRegistry(&$cache, $name, $type, $theme, $path)
	{
		$result = array();
		
		if (method_exists($theme, 'render'))
		{
			$result = $theme->render();
			
			foreach ($result as $model => $info)
			{
				$result[$model]['type'] = $type;
				$result[$model]['path'] = $path;
				
				$method = Renderer::methodForModel($model);
				
				if (isset($info['template']))
				{
					if (!empty($info['path']))
					{
						$result[$model]['callback'] = array($info['path'], $info['template']);
					}
					else
					{
						$result[$model]['callback'] = array($path, $info['template']);
					}
					
					$result[$model]['route'] = 'template';
				}
				else if (!isset($info['template']))
				{
					if (!isset($info['function']))
					{
						$result[$model]['callback'] = array(get_class($theme), ($type == RENDER_TYPE_MODULE ? 'render' . $method : lcfirst($method)));
						$result[$model]['route'] = 'method';
					}
					else
					{
						if (empty($info['function']) || !is_string($info['function'])) 
						{
							$info['function'] = $model;
						}
						
						$result[$model]['callback'] = ($type == RENDER_TYPE_MODULE ? 'render_' . $info['function'] : $name . '_' . $info['function']);
						$result[$model]['route'] = 'function';
					}
				}
				
				if (!isset($info['includes']))
				{
					$result[$model]['includes'] = array();
				}
				
				if (isset($info['file']))
				{
					$file = './' . $path . '/' . $info['file'];
					if (file_exists($file))
					{
						require_once ($file);
						$result[$model]['includes'][] = $file;
					}
					else
					{
						$file = './' . $file;
						if (file_exists($file))
						{
							require_once ($file);
							$result[$model]['includes'][] = $file;
						}
					}
				}
				
				if (!isset($info['arguments']) && isset($cache[$model]))
				{
					$result[$model]['arguments'] = $cache[$model]['arguments'];
				}
				
				if (!isset($info['prerender']) || !is_array($info['prerender']))
				{
					$info['prerender'] = array();
					
					if ($type == RENDER_TYPE_MODULE)
					{
						foreach (Moduler::moduleList() as $module_name)
						{
							$module = Moduler::moduleForName($module_name);
							$class = get_class($module);
							
							if (!isset($info['prerender'][$class]))
							{
								$info['prerender'][$class] = array();
							}
							
							if ($module->hooks('prerender'))
							{
								$info['prerender'][$class][] = 'prerender';
							}
							
							if ($module->hooks('prerender' . $method))
							{
								$info['prerender'][$class][] = 'prerender' . $method;
							}
						}
					}
					else
					{
						$class = get_class($theme);
						
						if (!isset($info['prerender'][$class]))
						{
							$info['prerender'][$class] = array();
						}
						
						if ($theme->hooks('prerender'))
						{
							$info['prerender'][$class][] = 'prerender';
						}
						
						if ($theme->hooks('prerender' . $method))
						{
							$info['prerender'][$class][] = 'prerender' . $method;
						}
					}
				}
				
				if (isset($cache[$model]['prerender']) && is_array($cache[$model]['prerender']))
				{
					$info['prerender'] = array_merge($cache[$model]['prerender'], $info['prerender']);
				}
				
				$result[$model]['prerender'] = $info['prerender'];
			}
			
			$cache = array_merge($cache, $result);
		}
		
		if ($type == RENDER_TYPE_THEME)
		{
			$class = get_class($theme);
			foreach ($cache as $model => $info)
			{
				$method = Renderer::methodForModel($model);
				
				if (!empty($info['template']) && empty($result[$model]))
				{
					if (!isset($info['prerender']))
					{
						$cache[$model]['prerender'] = array();
					}
					
					$cache[$model]['prerender'][$class] = array();
					
					if (method_exists($theme, 'prerender'))
					{
						$cache[$model]['prerender'][$class][] = 'prerender';
					}
					
					if (method_exists($theme, 'prerender' . $method))
					{
						$cache[$model]['prerender'][$class][] = 'prerender' . $model;
					}
					
					$cache[$model]['prerender'] = array_unique($cache[$model]['prerender']);
				}
			}
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param unknown_type $model
	 * @return Ambigous <string, mixed>
	 */
	public static function methodForModel($model)
	{
		$method = $model;
		$method = ucfirst($method);
		if (strpos($method, '_') !== FALSE)
		{
			while (($pos = strpos($method, '_')) !== FALSE)
			{
				$char = substr($method, $pos + 1, 1);
				$method = str_ireplace('_' . $char, strtoupper($char), $method);
			}
		}
		
		return $method;
	}

	/**
	 *
	 * @param <type> $theme
	 */
	public static function saveRegistry($theme)
	{
		$_this = & Renderer::getInstance();
		
		foreach ($_this->registry as $model => $info)
		{
			Db::query("UPDATE render SET path = %b, type = %d, route = '%s', callback = %b, includes = %b, prerender = %b, modified = %d WHERE model = '%s' AND theme = '%s'", $info['path'], $info['type'], $info['route'], serialize($info['callback']), serialize($info['includes']), 
				serialize($info['prerender']), time(), $model, $theme->name);
			
			if (!Db::affectedRows())
			{
				@Db::query("INSERT INTO render (model, theme, path, type, route, callback, arguments, includes, prerender, modified) VALUES ('%s', '%s', %b, %d, '%s', %b, %b, %b, %b, %d)", $model, $theme->name, $info['path'], $info['type'], $info['route'], serialize($info['callback']), 
					serialize($info['arguments']), serialize($info['includes']), serialize($info['prerender']), time());
			}
		}
		
		Renderer::cacheRegistry($theme);
	}

	/**
	 *
	 * @param <type> $theme
	 */
	public static function cacheRegistry($theme)
	{
		$_this = & Renderer::getInstance();
		Storage::cacheSet('renderer_registry:' . $theme->name, $_this->registry);
	}

	/**
	 * loadRegistry()
	 * 
	 * Enter description here ...
	 * 
	 * @param string $theme
	 * @param string $base_theme
	 * @param string $theme_engine
	 */
	public static function loadRegistry($theme, $base_theme = NULL, $theme_engine = NULL)
	{
		$cache = Storage::cacheGet('renderer_registry:' . $theme->name);
		
		if (isset($cache->data))
		{
			$_this = & Renderer::getInstance();
			$_this->registry = $cache->data;
		}
		else
		{
			Renderer::buildRegistry($theme, $base_theme, $theme_engine);
		}
	}

	/**
	 * loadOfflineRegistry()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $theme
	 * @param unknown_type $base_theme
	 * @param unknown_type $theme_engine
	 */
	public static function loadOfflineRegistry($theme, $base_theme = NULL, $theme_engine = NULL)
	{
		Renderer::buildRegistry($theme, $base_theme, $theme_engine);
	}

	/**
	 * listThemes()
	 * 
	 * Enter description here ...
	 * 
	 * @param unknown_type $refresh
	 */
	public static function listThemes($refresh = FALSE)
	{
		$_this = & Renderer::getInstance();
		if ($refresh)
		{
			$_this->themes = array();
		}
		
		if (empty($_this->themes))
		{
			$themes = array();
			if (Db::isActive() && !defined('CONFIGURATION_MODE'))
			{
				$result = Db::query("SELECT * FROM system WHERE type = '%s'", 'theme');
				while (($theme = Db::fetchObject($result)) !== FALSE)
				{
					if (file_exists($theme->file))
					{
						$theme->info = unserialize($theme->info);
						$themes[] = $theme;
					}
				}
			}
			else
			{
				$themes = Renderer::_themeData();
			}
		}
	}

	/**
	 *
	 * @return <type> 
	 */
	public static function _themeData()
	{
		$_this = & Renderer::getInstance();
		if (empty($_this->themes))
		{
			$themes = Athena::system_listing('\.info$', 'themes');
			
			$engines = Athena::system_listing('\.engine$', 'themes/engines');
			
			$defaults = System::themeDefaults();
			
			$config = array();
			foreach ($themes as $key => $theme)
			{
				$name = basename($theme->basename, '.info');
				$config[$name] = $defaults;
				include_once ($theme->filename);
				
				$pathed_stylesheets = array();
				foreach ($config[$name]['stylesheets'] as $media => $stylesheets)
				{
					foreach ($stylesheets as $stylesheet)
					{
						$pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->filename) . '/' . $stylesheet;
					}
				}
				
				$config[$name]['stylesheets'] = $pathed_stylesheets;
				
				$scripts = array();
				foreach ($config[$name]['scripts'] as $script)
				{
					$scripts[$script] = dirname($themes[$key]->filename) . '/' . $script;
				}
				
				$config[$name]['scripts'] = $scripts;
				
				if (!empty($config[$name]['screenshot']))
				{
					$config[$name]['screenshot'] = dirname($themes[$key]->filename) . '/' . $config[$name]['screenshot'];
				}
				
				$themes[$key]->info = $config[$name];
			}
			
			$_this->themes = $themes;
		}
		
		return $_this->themes;
	}

	/**
	 * Enter description here ...
	 * 
	 * @return array    
	 */
	public static function commonTheme()
	{
		return array(
			'placeholder' => array(
				'arguments' => array(
					'text' => NULL
				)
			), 
			'page' => array(
				'arguments' => array(
					'content' => NULL, 
					'show_blocks' => TRUE, 
					'show_messages' => TRUE
				), 
				'template' => 'page'
			), 
			'maintenance_page' => array(
				'arguments' => array(
					'content' => NULL, 
					'show_blocks' => TRUE, 
					'show_messages' => TRUE
				), 
				'template' => 'maintenance-page'
			), 
			'update_page' => array(
				'arguments' => array(
					'content' => NULL, 
					'show_messages' => TRUE
				)
			), 
			'install_page' => array(
				'arguments' => array(
					'content' => NULL
				), 
				'function' => 'install_page'
			), 
			'task_list' => array(
				'arguments' => array(
					'items' => NULL, 
					'active' => NULL
				), 
				'function' => 'task_list'
			), 
			'status_messages' => array(
				'arguments' => array(
					'display' => NULL
				)
			), 
			'system_messages' => array(
				'arguments' => array(
					'display' => NULL
				), 
				'function' => 'system_messages'
			), 
			'links' => array(
				'arguments' => array(
					'links' => NULL, 
					'attributes' => array(
						'class' => 'links'
					)
				), 
				'function' => 'links'
			), 
			'image' => array(
				'arguments' => array(
					'path' => NULL, 
					'alt' => '', 
					'title' => '', 
					'attributes' => NULL, 
					'getsize' => TRUE
				),
				'function' => TRUE
			), 
			'breadcrumbs' => array(
				'arguments' => array(
					'breadcrumbs' => NULL
				),
				'function' => TRUE
			), 
			'help' => array(
				'arguments' => array()
			), 
			'submenu' => array(
				'arguments' => array(
					'links' => NULL
				)
			), 
			'table' => array(
				'arguments' => array(
					'header' => NULL, 
					'rows' => NULL, 
					'attributes' => array(), 
					'caption' => NULL
				)
			), 
			'table_select_header_cell' => array(
				'arguments' => array()
			), 
			'tablesort_indicator' => array(
				'arguments' => array(
					'style' => NULL
				)
			), 
			'box' => array(
				'arguments' => array(
					'title' => NULL, 
					'content' => NULL, 
					'region' => 'main'
				), 
				'template' => 'box'
			), 
			'block' => array(
				'arguments' => array(
					'block' => NULL
				), 
				'template' => 'block'
			), 
			'mark' => array(
				'arguments' => array(
					'type' => MARK_NEW
				)
			), 
			'item_list' => array(
				'arguments' => array(
					'items' => array(), 
					'title' => NULL, 
					'type' => 'ul', 
					'attributes' => NULL
				)
			), 
			'more_help_link' => array(
				'arguments' => array(
					'url' => NULL
				)
			), 
			'xml_icon' => array(
				'arguments' => array(
					'url' => NULL
				)
			), 
			'feed_icon' => array(
				'arguments' => array(
					'url' => NULL, 
					'title' => NULL
				)
			), 
			'more_link' => array(
				'arguments' => array(
					'url' => NULL, 
					'title' => NULL
				)
			), 
			'closure' => array(
				'arguments' => array(
					'main' => 0
				)
			), 
			'blocks' => array(
				'arguments' => array(
					'region' => NULL
				)
			), 
			'username' => array(
				'arguments' => array(
					'object' => NULL
				)
			), 
			'progress_bar' => array(
				'arguments' => array(
					'percent' => NULL, 
					'message' => NULL
				),
				'function' => TRUE
			), 
			'indentation' => array(
				'arguments' => array(
					'size' => 1
				)
			),  // from pager.inc
			'pager' => array(
				'arguments' => array(
					'tags' => array(), 
					'limit' => 10, 
					'element' => 0, 
					'parameters' => array()
				)
			), 
			'pager_first' => array(
				'arguments' => array(
					'text' => NULL, 
					'limit' => NULL, 
					'element' => 0, 
					'parameters' => array()
				)
			), 
			'pager_previous' => array(
				'arguments' => array(
					'text' => NULL, 
					'limit' => NULL, 
					'element' => 0, 
					'interval' => 1, 
					'parameters' => array()
				)
			), 
			'pager_next' => array(
				'arguments' => array(
					'text' => NULL, 
					'limit' => NULL, 
					'element' => 0, 
					'interval' => 1, 
					'parameters' => array()
				)
			), 
			'pager_last' => array(
				'arguments' => array(
					'text' => NULL, 
					'limit' => NULL, 
					'element' => 0, 
					'parameters' => array()
				)
			), 
			'pager_link' => array(
				'arguments' => array(
					'text' => NULL, 
					'page_new' => NULL, 
					'element' => NULL, 
					'parameters' => array(), 
					'attributes' => array()
				)
			),  // from locale.inc
			'locale_admin_manage_screen' => array(
				'arguments' => array(
					'form' => NULL
				)
			),  // from menu.inc
			'menu_item_link' => array(
				'arguments' => array(
					'item' => NULL
				)
			), 
			'menu_tree' => array(
				'arguments' => array(
					'tree' => NULL
				)
			), 
			'menu_item' => array(
				'arguments' => array(
					'link' => NULL, 
					'has_children' => NULL, 
					'menu' => ''
				)
			), 
			'menu_local_task' => array(
				'arguments' => array(
					'link' => NULL, 
					'active' => FALSE
				)
			), 
			'menu_local_tasks' => array(
				'arguments' => array()
			),  // from form.inc
			'select' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'fieldset' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'radio' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'radios' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'password_confirm' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'date' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'item' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'checkbox' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'checkboxes' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'submit' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'button' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'image_button' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'hidden' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'token' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'textfield' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'form' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'textarea' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'markup' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'password' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'file' => array(
				'arguments' => array(
					'element' => NULL
				)
			), 
			'form_element' => array(
				'arguments' => array(
					'element' => NULL, 
					'value' => NULL
				)
			)
		);
	}
}

/**
 * render()
 * 
 * Enter description here ...
 * 
 * @return Ambiguous
 */
function render()
{
	$args = func_get_args();
	
	return call_user_func_array(array('Renderer', 'render'), $args);
}

/**
 * render_attributes()
 * 
 * This is a function that will take in a key => value array 
 * and produce a string of HTML attributes.
 * 
 * ie. an array like array('class' => 'navigation') will return ' class="navigation"'
 * 
 * @param mixed $attributes
 * @return
 */
/*
function render_attributes($attributes = array())
{
	if (is_array($attributes))
	{
		$output = '';
		foreach ($attributes as $key => $value)
		{
			$output .= " $key=" . '"' . html_safe($value) . '"';
		}
		
		return $output;
	}
}
*/

/**
 * Theme a heading (ie. <h1> element).
 * 
 * @param $text: the text to be included in the heading. Not translated here.
 * @param $level: the level of the heading (1 - 6).
 * @param $attributes: Optional attributes.
 * @return themed heading.
 */
/*
function render_heading($text, $level = 2, $attributes = array())
{
	if ($level > 6 || $level < 1)
	{
		Athena::setMessage('Invalid heading level requested ' . $level, 'error');
		$level = 6;
	}
	
	return "<h$level " . render_attributes($attributes) . '>' . $text . "</h$level>";
}
*/

/**
 * Enter description here ...
 * 
 * @param unknown_type $breadcrumbs
 * @return string
 */
function render_breadcrumbs($breadcrumbs)
{
	$output = '';
	if (!empty($breadcrumbs))
	{
		$separator = '</li><li class="breadcrumb"> > </li><li class="breadcrumb">';
		
		$output = '<div class="breadcrumbs"><ul><li class="breadcrumb first">' . implode($separator, $breadcrumbs) . '</li><li class="breadcrumb"> > </li><li class="breadcrumb last">' . page_title() . '</li></ul></div>';
	}
	
	return $output;
}

/**
 * render_system_messages()
 * 
 * @param mixed $messages
 * @return
 */
function render_system_messages($display = NULL)
{
	$output = '';
	
	$messages = Athena::getMessages();
	
	if (empty($display))
	{
		foreach ($messages as $type => $message_list)
		{
			$output .= _render_system_messages($type, $message_list);
		}
	}
	else
	{
		$output .= _render_system_messages($display, $messages[$display]);
	}
	
	return $output;
}

/**
 * _render_system_messages()
 * 
 * Enter description here ...
 * 
 * @param string $type
 * @param array $message_list
 * @return string
 */
function _render_system_messages($type, $message_list)
{
	$output = '';
	
	if (!empty($message_list))
	{
		$output .= '<div class="' . $type . '"><ul>' . "\n";
		
		for ($i = 0; $i < count($message_list); $i++)
		{
			$output .= '<li class="message">' . $message_list[$i] . '</li>' . "\n";
		}
		
		$output .= '</ul></div>' . "\n";
	}
	
	return $output;
}

/**
 * render_menu()
 * 
 * Renders those menu links
 * 
 * @param mixed $menu
 * @return
 */
function render_menu($menu)
{
	return render_links($menu, array('class' => 'ui-navigation menu'));
}

/**
 * render_links()
 * 
 * Generally renders and links in a list
 * 
 * @param mixed $links
 * @param mixed $attributes
 * @return
 */
function render_links($links, $attributes = array('class' => 'links'))
{
	$q = $_GET['q'];
	
	$output = '';
	$count = count($links);
	if ($count > 0)
	{
		$output = '<ul' . attributes($attributes) . '>' . "\n";
		
		$i = 0;
		foreach ($links as $key => $link)
		{
			$classes = array('link-item');
			
			$classes[] = ($i + 1) % 2 == 0 ? 'even' : 'odd';
			
			if ($i == 0)
			{
				$classes[] = 'first';
			}
			else if ($i == $count - 1)
			{
				$classes[] = 'last';
			}
			
			if (isset($link['#href']) && $link['#href'] == $q)
			{
				$class[] = 'active';
			}
			
			$output .= '<li class="' . implode(' ', $classes) . '">' . a($link) . '</li>' . "\n";
			$i++;
		}
		
		$output .= '</ul>' . "\n";
	}
	
	return $output;
}

/**
 * Return a themed progress bar.
 *
 * @param $percent
 * The percentage of the progress.
 * @param $message
 * A string containing information to be displayed.
 * @return
 * A themed HTML string representing the progress bar.
 */
function render_progress_bar($percent, $message)
{
	$output = '<div id="progress" class="progress">';
	$output .= '<div class="bar"><div class="filled" style="width: ' . $percent . '%"></div></div>';
	$output .= '<div class="percentage">' . $percent . '%</div>';
	$output .= '<div class="message">' . $message . '</div>';
	$output .= '</div>';
	
	return $output;
}
